<template>
  <div
    v-show="selfVisible"
    ref="popupRef"
    class="
      personnel-selector-popup absolute w-48 z-1
      border border-solid border-gray-100 rounded-sm shadow
      overflow-hidden bg-white select-none"
    :style="{
      ...selfPosition,
    }"
  >
    <!-- 标题栏 -->
    <div
      class="flex justify-between p-3 border-b border-solid border-b-gray-50 text-sm"
    >
      <span class="teld-color-gray">
        <!-- {{ keyword ? '选择提及人员' : '最近提及人员' }} -->
        {{ keyword ? qLangComment.toSelectMentions : qLangComment.recentlyMentions }}
      </span>
      <!-- <span @click="onClickMore" class="teld-theme-color cursor-pointer"
        >更多</span
      > -->
    </div>

    <!-- 内容区域 -->
    <!-- 有 keyword 时，展示查询结果 -->
    <div
      v-show="keyword"
      class="query-user-list px-1 overflow-y-auto"
      :class="[loading ? 'h-41' : 'max-h-41']"
    >
      <div
        v-show="!loading && !userList.length"
        class="teld-color-gray p-3 flex justify-center items-center h-full"
      >
        <!-- 没有符合条件的数据 -->
        {{ qLangComment.noData }}
      </div>
      <div
        v-for="(item, index) in userList"
        :key="item.UserID"
        :data-item-index="index"
        class="user-item flex items-center p-2 hover:bg-gray-100"
        :class="[
          activeIndex === index ? 'bg-gray-100' : '',
          index === userList.length - 1 ? '' : 'mb-0.5',
        ]"
        @click.capture.stop="onClickItem(item, index)"
      >
        <UserAvatar
          :image-url="item.Avatar"
          class="cursor-pointer"
          :classList="['rounded']"
          @mouseenter.native="onEnter($event, item)"
          @mouseleave.native="onLeave()"
        />
        <div class="ml-4 flex-1 truncate" :title="item.RealName">
          {{ item.RealName }}
        </div>
      </div>
      <t-inner-loading :showing="loading">
        <t-spinner size="28px" color="primary" />
      </t-inner-loading>
    </div>

    <!-- 没有 keyword 时，展示最近历史 -->
    <div
      v-show="!keyword"
      ref="recentUserListRef"
      class="recent-user-list max-h-41 px-1 overflow-y-auto"
    >
      <div
        v-if="!recentlyMentionedUsers.length"
        class="p-3 teld-color-gray"
      >
        {{ /*暂无最近提及的人员，输入人名进行搜索*/ qLangComment.noRecentlyMentions }}
      </div>
      <div
        v-else
        v-for="(item, index) in recentlyMentionedUsers"
        :key="item.UserID"
        :data-item-index="index"
        class="user-item flex items-center p-2 hover:bg-gray-100"
        :class="[
          activeIndex === index ? 'bg-gray-100' : '',
          index === recentlyMentionedUsers.length - 1 ? '' : 'mb-0.5',
        ]"
        @click="onClickItem(item, index)"
      >
        <UserAvatar
          :image-url="item.Avatar"
          class="cursor-pointer"
          :classList="['rounded']"
          @mouseenter="onEnter($event, item)"
          @mouseleave="onLeave(item)"
        />
        <span class="ml-4 flex-1 truncate" :title="item.RealName">
          {{ item.RealName }}
        </span>
      </div>
    </div>
  </div>
</template>

<script>
// Components
import UserAvatar from '../../components/user-avatar/index.vue';

// Utils
import {
  getRangeRect,
  debounce,
} from '../../hooks';
import {TELD_ORG_ID,
SG_USER_LIST_QUERY_FIELDS,
} from '../../utils';
import { getSysCommonUserList } from '../../hooks/api.js'

/**
 * @summary 自定义实现评论输入框，支持`@`选人的富文本交互
 */
export default {
  name: 'PersonnelSelectorPopup',
  inject: [
    'qLangComment',
    // 'getRecentlyMentionedUsers',
    'recentlyMentionedUsers',
    'showPersonnelInfo',
    'hidePersonnelInfo',
  ],
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
    keyword: {
      type: String,
      default: '',
    },
    /**简易选人popup确定位置用的参照系元素*/
    offsetParent: {
      type: HTMLElement,
    },
    // --------------------------
    onPick: {
      type: Function,
    },
    // --------------------------
  },
  components: {
    UserAvatar,
  },
  data() {
    return {
      activeIndex: 0,
      selfPosition: {},
      userList: [],
      loading: false,
    };
  },
  computed: {
    selfVisible: {
      get() {
        return this.visible;
      },
      set(val) {
        this.$emit('update:visible', val);
      },
    },
    currentList() {
      // return this.keyword ? this.userList : this.getRecentlyMentionedUsers();
      return this.keyword ? this.userList : this.recentlyMentionedUsers;
    },
  },
  watch: {
    visible(val) {
      if (val) {
        document.addEventListener('keydown', this.onKeyDown, true);
        this.$nextTick(() => {
          this.$refs.recentUserListRef.scrollTop = 0;
          this.updatePosition();
        });
      } else {
        this.activeIndex = 0;
        document.removeEventListener('keydown', this.onKeyDown, true);
      }
    },
    async keyword(val) {
      this.activeIndex = 0;
      if (val) {
        if (this.loading) {
          setTimeout(() => {
            this.debouncedLoadList();
          }, 50);
          return;
        }
        // search data and update position
        await this.loadList();
      } else {
        this.userList = [];
        this.$nextTick(() => {
          this.updatePosition();
        });
      }
    },
    activeIndex(val) {
      const ele = this.$el.querySelector(`div[data-item-index="${val}"]`);
      const rect = ele.getBoundingClientRect();
      const rectParent = ele.parentElement.getBoundingClientRect();
      if (rect.bottom > rectParent.bottom || rect.top < rectParent.top) {
        ele.scrollIntoView({ block: 'nearest' });
      }
    },
  },
  methods: {
    getKeyFiled(val) {
      // const regExpCName = /[\\u4E00-\\u9FFF]+/g;
      const regExpCName = /^[\u4E00-\u9FFF]+$/;
      // 正则识别邮箱：不是要验证邮箱是否合法，而是用于搜索时，识别到输入的是邮箱，即使还没输入完整
      // const regExpEmail = /^[a-z0-9_.-]+@[a-z0-9-]+(\.[a-z0-9-]+)*\.([a-z]+)$/i;
      const regExpEmail = /^[a-z0-9_.-]+@[a-z0-9-]*(\.[a-z0-9-]*)*(\.[a-z]*){0,}$/i;
      const regExpPhone = /^\d+$/; // 不固定位数因为手机号支持模糊查询

      if (regExpCName.test(val)) {
        this.matchField = SG_USER_LIST_QUERY_FIELDS.REAL_NAME;
      } else if (regExpEmail.test(val)) {
        this.matchField = SG_USER_LIST_QUERY_FIELDS.EMAIL;
      } else if (regExpPhone.test(val)) {
        this.matchField = SG_USER_LIST_QUERY_FIELDS.MOBILE;
      } else {
        this.matchField = SG_USER_LIST_QUERY_FIELDS.ACCOUNT;
      }
      return this.matchField;
    },
    /** 获取用户数据列表 */
    async loadList() {
      this.loading = true;
      const fieldName = this.getKeyFiled(this.keyword);
      console.log('query field', this.keyword, fieldName);

      const payload = {
        // FieldName: 'RealName',
        FieldName: fieldName,
        FieldValue: this.keyword,
        FilterKey: {
          Data_FunctionID: 'DF686BBF-2387-4259-886B-249022156A8A',
          Enabled: 1,
          FilterByPeakOrgID: TELD_ORG_ID,
          NoDataAuth: 'true',
        },
        page: 1,
        rows: 20,
      };

      try {
        // const { data } = await this.$utils.sgApi.getDataAsync({
        //   url: this.$utils.common.getServiceUrl(
        //     'SYS_CommonHelper_GetUserList&help=true',
        //   ),
        //   method: 'POST',
        //   data: { filter: JSON.stringify(payload) },
        // });
        const res = await getSysCommonUserList(payload);

        if (!res) {
          this.userList = [];
          return;
        }
        const { total, rows } = res;
        this.userList = rows;
        console.log('userList', rows);
      } catch (error) {
        this.userList = [];
        console.log(error);
      } finally {
        console.log('finally', this.userList);
        this.$nextTick(() => {
          this.loading = false;
          setTimeout(() => {
            this.updatePosition();
          }, 300);
        });
      }
    },
    /** 防抖后的loadList */
    debouncedLoadList: debounce(function() {
      this.loadList();
    }, 500),
    updatePosition() {
      if (!this.$refs.popupRef || !this.visible) return {};

      const LINE_HEIGHT = 20;
      const MARGIN_GAP = 8;
      const position = { left: null, top: null };

      const popupRect = this.$refs.popupRef.getBoundingClientRect();
      const textRect = getRangeRect();
      const containerRect = this.offsetParent.getBoundingClientRect();
      const containerScrollTop = this.offsetParent.scrollTop;

      // 判断边界
      // --超出右侧边界--
      if (containerRect.right - textRect.right - MARGIN_GAP < popupRect.width) {
        // 小屏幕情况下左侧也空间不足的话
        if (textRect.left - containerRect.left - MARGIN_GAP < popupRect.width) {
          position.left = '0';
        } else {
          position.left = `${textRect.left -
            containerRect.left -
            popupRect.width -
            MARGIN_GAP}px`;
        }
      } else {
        position.left = `${textRect.left - containerRect.left + MARGIN_GAP}px`;
      }

      // --超出下侧边界--
      if (
        containerRect.bottom - textRect.bottom - LINE_HEIGHT <
        popupRect.height
      ) {
        // 当正好在中间位置输入时就可能造成上下两边都空间不足的情况：上边也不足的时候
        if (textRect.top - containerRect.top < popupRect.height) {
          position.top = '0';
        } else {
          position.top = `${textRect.top -
            containerRect.top -
            popupRect.height +
            containerScrollTop}px`;
        }
      } else {
        position.top = `${textRect.top -
          containerRect.top +
          LINE_HEIGHT +
          containerScrollTop}px`;
      }

      this.selfPosition = position;
    },
    onKeyDown(e) {
      if (e.key === 'ArrowDown') {
        e.preventDefault();
        this.activeIndex += 1;
        if (this.activeIndex >= this.currentList.length) {
          this.activeIndex = 0;
        }
      } else if (e.key === 'ArrowUp') {
        e.preventDefault();
        this.activeIndex -= 1;
        if (this.activeIndex < 0) {
          this.activeIndex = this.currentList.length - 1;
        }
      } else if (e.key === 'Enter') {
        e.preventDefault();
        this.handlePickUser();
      }
    },
    /**
     * @summary 点击数据条目
     * @param {*} item
     * @param {*} itemIndex
     * @description
     * select-none 使其不能在 click 时转移焦点，以保障输入框中能正确地插入内容
     */
    onClickItem(item, itemIndex) {
      this.activeIndex = itemIndex;
      this.$emit('selected', item);
    },
    handlePickUser() {
      if (!this.currentList || !this.currentList.length) {
        return;
      }
      this.$emit('selected', this.currentList[this.activeIndex]);
    },
    onClickMore() {
      this.$emit('show-more');
    },
    onEnter(e, item) {
      this.showPersonnelInfo({
        target: e.target,
        info: item,
        disableUserSelect: true,
      });
    },
    onLeave() {
      this.hidePersonnelInfo();
    },
  },
};
</script>

<style>
.personnel-selector-popup {
  transition: all 100ms;
}
</style>
